package classloader;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class reflectOuter {
    public reflectOuter(String cpath){
        //запросить директорию
        //String cpath = "codeBase";
        //запросить имя класса
        String cname="";
        //создать собственный загрузчик классов
        ClassLoader loader = new MyClassLoader(cpath);
        for(File file:getFileList(new File(cpath))){
            try{// загрузить класс
                cname=file.getPath();
                cname=cname.substring(cpath.length()+1, cname.length()-6);
                cname=cname.replace('\\', '.');
                Class cl = loader.loadClass(cname);
                System.out.println("Class loaded: "+file.getPath());
            }catch (Exception e) {
                System.out.println("Can't open class: "+file.getPath());}
        }
        System.out.println("All classes loaded");
    }
    
    /**
     * Запросить содержимое директории, включая содержимое вложенных директорий
     * @param dir - директория
     */
    private static List<File> getFileList(File dir){
        //массив для выборки
    	ArrayList<File> list= new ArrayList<File>();
        //запросить содержимое директории
        String[] children = dir.list();
        File tmp;
        //обход по содержимому
        for (int i=0; i<children.length; i++) {
        	tmp=new File(dir,children[i]);
            //если содержимое - директория, получить её содержимое
        	if(tmp.isDirectory()){
                //рекурсивный вызов
        		list.addAll(getFileList(tmp));
        	}
            else{
                //проверить необходимость добавления файлов в выборку
                list.add(tmp);
            }
        }
        //верныть выборку
        return list;
    }
}
/** Пользовательский загрузчик классов */
class MyClassLoader extends ClassLoader{
    private String path; // дирректория для поиска
    public MyClassLoader (String path)
         { this.path=path; }
@Override
    protected Class findClass(String name)
    throws ClassNotFoundException{
        //сгенерировать имя файла
        String fname= path + '/' + name.replace('.', '/')+".class";
        FileInputStream in = null;
        ByteArrayOutputStream classBytes=null;
        int ch;
        //прочитать файл
        try{
            in = new FileInputStream(fname);
        }catch(Exception e){throw new
            ClassNotFoundException(name);}
        //загрузить последовательность байт
        try{
            classBytes = new ByteArrayOutputStream();
            while((ch=in.read())!=-1)
                classBytes.write((byte) ch);
            in.close();
        }catch(Exception e){
            try{in.close();}catch(Exception ex){}
            throw new ClassNotFoundException(name);
        }
        //создать класс
        Class cl = defineClass(name,
              classBytes.toByteArray(),
              0, classBytes.size());
        if(cl==null) throw new
               ClassNotFoundException(name);
        return cl;
    } // конец findClass()
} // конец класса
